/*
 * @Author: song
 * @Description:技能编译器配置
 * @Date: 2024年05月03日 星期五 22:05:30
 * @Modify:
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Function.SkillEditor.Editor;
using SCore.Editor.WindowDraw;
using Function.SerializedPropertyAttribute;
using Function.SkillEditor.Runtime;
using SCore.Util;
using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;

namespace Function.SkillEditor.Editor
{
    [CustomEditor(typeof(SkillEditorConfig))]
    public class SkillEditorConfigEditor : ObjectDrawEditor<SkillEditorConfig>
    {
    }

    [Serializable]
    public class SkillWindowConfig
    {
        [SerializeField] public List<ECommonView> _eCommonViews;
    }

    [CreateAssetMenu(fileName = "SkillEditorConfig", menuName = "ScriptableObject/SkillEditor/Config", order = 3)]
    public class SkillEditorConfig : SingleScriptableObject<SkillEditorConfig>
    {
        [Foldout("技能Map 编辑器配置---Editor", true)] [SerializeField]
        private List<SkillConfigItemData> _map;

        [Foldout("技能编辑组件配置---Static", true)] [SerializeField]
        private SerializableDictionary<SkillWindowType, SkillWindowConfig> _componentMap =
            new SerializableDictionary<SkillWindowType, SkillWindowConfig>();

        [Foldout("基础设置---Static", true)] [Head("导出路径---Static")] [DirectoryField]
        public string _outPutPath;

        [Head("骨骼名")] public List<string> _bindNames;

        [Foldout("美化---Static", true)] [Head("轨道左边分颜色")]
        public Color _leftTrackColor = EditorDrawHelp.HexToColor("#D2D2D2");

        [Head("轨道选中颜色")] public Color _selectTrackColor;
        [Head("轨道右边默认颜色")] public Color _rightTrackColor = EditorDrawHelp.HexToColor("#999999");
        [Head("轨道Clip默认颜色")] public Color _clipColor = EditorDrawHelp.HexToColor("#888D94");
        [Head("轨道Clip被选中颜色")] public Color _clipSelectColor = EditorDrawHelp.HexToColor("#52211F");

        /// <summary>
        /// 得到界面的配置
        /// </summary>
        /// <param name="skillWindowType"></param>
        /// <returns></returns>
        public SkillWindowConfig GetWindowConfig(SkillWindowType skillWindowType)
        {
            if (_componentMap.TryGetValue(skillWindowType, out var config))
            {
                return config;
            }

            return null;
        }


        public GUIContent[] GetBindContent()
        {
            List<GUIContent> bindContents = new List<GUIContent>();
            foreach (var bindName in _bindNames)
            {
                bindContents.Add(new GUIContent(bindName));
            }

            return bindContents.ToArray();
        }

        /// <summary>
        /// 创建技能RunLine实例
        /// </summary>
        /// <param name="id">id</param>
        /// <returns></returns>
        public SkillRunLine CreateSkillRunLine(int id)
        {
            var skillRunLine = CreateInstance<SkillRunLine>();
            skillRunLine._lineId = id;
            return skillRunLine;
        }

        /// <summary>
        /// 删除技能RunLine配置
        /// </summary>
        /// <param name="skillRunLine">技能RunLine</param>
        public void DelSkillRunLine(SkillRunLine skillRunLine)
        {
            if (skillRunLine != null)
            {
                string path = _outPutPath + $"/{skillRunLine._lineId}.asset";
                if (File.Exists(path))
                    AssetDatabase.DeleteAsset(path);
            }
        }

        /// <summary>
        /// 保存技能runline实例
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public void SaveSkillRunLine(SkillRunLine copyData)
        {
            string path = _outPutPath + $"/{copyData._lineId}.asset";
            if (File.Exists(path))
            {
                var skillRunLine = AssetDatabase.LoadAssetAtPath<SkillRunLine>(path);
                if (!skillRunLine.Equals(copyData) && skillRunLine != copyData)
                {
                    skillRunLine._lineId = copyData._lineId;
                    skillRunLine._lengthFrame = copyData._lengthFrame;
                    for (int offest = skillRunLine._skillTracks.Count - 1; offest >= 0; offest--)
                    {
                        var assetSkillTrack = skillRunLine._skillTracks[offest];
                        var clips = assetSkillTrack.GetClips();
                        for (int clipOffest = clips.Count - 1; clipOffest >= 0; clipOffest--)
                        {
                            DelSkillClip(clips[clipOffest]);
                        }

                        assetSkillTrack.Clear();
                        DelSkillTrack(assetSkillTrack);
                    }

                    skillRunLine._skillTracks.Clear();
                    SaveAllSkillTrack(copyData._skillTracks, skillRunLine);
                    EditorUtility.SetDirty(skillRunLine);
                    AssetDatabase.SaveAssetIfDirty(skillRunLine);
                }
            }
            else
            {
                //创建实例
                var skillRunLine = CreateInstance<SkillRunLine>();
                skillRunLine._lineId = copyData._lineId;
                skillRunLine._lengthFrame = copyData._lengthFrame;
                AssetDatabase.CreateAsset(skillRunLine, path);
                if (copyData._skillTracks != null)
                {
                    SaveAllSkillTrack(copyData._skillTracks, skillRunLine);
                }

                EditorUtility.SetDirty(skillRunLine);
                AssetDatabase.SaveAssetIfDirty(skillRunLine);
            }
        }


        /// <summary>
        /// 创建技能轨道
        /// </summary>
        /// <param name="skillRunLine">runline</param>
        /// <param name="sKillTrackType">轨道类型</param>
        /// <typeparam name="T"></typeparam>
        public void CreateSkillTrack<T>(SkillRunLine skillRunLine) where T : SkillTrack
        {
            T instance = CreateInstance<T>();
            skillRunLine._skillTracks.Add(instance);
        }

        public void CreateSkillTrack(Type type, SkillRunLine skillRunLine)
        {
            var instance = CreateInstance(type) as SkillTrack;
            if (instance != null)
            {
                skillRunLine._skillTracks.Add(instance);
            }
        }

        /// <summary>
        /// 保存所有技能轨道
        /// </summary>
        /// <param name="skillTracks"></param>
        /// <param name="skillRunLine"></param>
        public void SaveAllSkillTrack(List<SkillTrack> skillTracks, SkillRunLine skillRunLine)
        {
            Dictionary<SkillClip, SkillClip> clipSaveMap = new Dictionary<SkillClip, SkillClip>();

            var part1Clip = skillTracks.FindAll((clip) => { return !(clip is SkillBuffTrack); });
            foreach (var clip in part1Clip)
            {
                SaveSkillTrack(clip, skillRunLine, ref clipSaveMap);
            }

            var part2Clip = skillTracks.FindAll((clip) => { return clip is SkillBuffTrack; });
            foreach (var clip in part2Clip)
            {
                SaveSkillTrack(clip, skillRunLine, ref clipSaveMap);
            }
        }

        /// <summary>
        /// 创建技能轨道
        /// </summary>
        /// <param name="skillRunLine">runline</param>
        /// <param name="sKillTrackType">轨道类型</param>
        public void SaveSkillTrack(SkillTrack skillTrack, SkillRunLine skillRunLine,
            ref Dictionary<SkillClip, SkillClip> clipSaveMap)
        {
            var copyTrack = Instantiate(skillTrack);
            var copyname = copyTrack.GetType().ToString();
            copyTrack.name =
                copyname.Substring(copyname.LastIndexOf(".") + 1, copyname.Length - copyname.LastIndexOf(".") - 1);
            copyTrack.Clear();
            AssetDatabase.AddObjectToAsset(copyTrack, skillRunLine);
            skillRunLine._skillTracks.Add(copyTrack);
            var skillClip = skillTrack.GetClips();
            for (int offest = skillClip.Count - 1; offest >= 0; offest--)
            {
                var copyClip = Instantiate(skillClip[offest]);
                clipSaveMap.Add(skillClip[offest], copyClip);
                var clipName = copyClip.GetType().ToString();
                copyClip.name =
                    clipName.Substring(clipName.LastIndexOf(".") + 1, clipName.Length - clipName.LastIndexOf(".") - 1);
                AssetDatabase.AddObjectToAsset(copyClip, copyTrack);
                copyTrack.GetClips().Add(copyClip);
                //SkillBuffClip
                if (copyClip is SkillBuffClip)
                {
                    var buffClip = copyClip.As<SkillBuffClip>();
                    List<SkillTriggerClip> saveClips = new List<SkillTriggerClip>();
                    foreach (var triggerClip in buffClip._triggers)
                    {
                        saveClips.Add(clipSaveMap[triggerClip] as SkillTriggerClip);
                    }

                    buffClip._triggers = saveClips;
                }
            }
        }


        /// <summary>
        /// 删除运行的时候实例技能轨道
        /// </summary>
        /// <param name="skillRunLine"></param>
        /// <param name="skillTrack"></param>
        public void DelRunSkillTrack(SkillRunLine skillRunLine, SkillTrack skillTrack)
        {
            skillRunLine._skillTracks.Remove(skillTrack);
        }

        /// <summary>
        /// 真实的删除技能轨道
        /// </summary>
        /// <param name="skillTrack"></param>
        public void DelSkillTrack(SkillTrack skillTrack)
        {
            AssetDatabase.RemoveObjectFromAsset(skillTrack);
        }


        /// <summary>
        /// 真实的删除技能轨道
        /// </summary>
        /// <param name="skillTrack"></param>
        public void DelSkillClip(SkillClip skillTrack)
        {
            AssetDatabase.RemoveObjectFromAsset(skillTrack);
        }

        /// <summary>
        /// 添加技能Map Item
        /// </summary>
        /// <returns></returns>
        public SkillConfigItemData AddMap(int id)
        {
            var itemData = new SkillConfigItemData()
            {
                _name = "please edit",
                _id = id,
            };
            _map.Add(itemData);
            return itemData;
        }

        /// <summary>
        /// 得到技能Map
        /// </summary>
        /// <returns></returns>
        public List<SkillConfigItemData> GetMap()
        {
            return _map;
        }

        /// <summary>
        /// 保存编译器配置Map数据
        /// </summary>
        /// <param name="config"></param>
        public void SaveBy(SkillEditorConfig config)
        {
            var selfMap = _map; //当前Map
            _map = config.GetMap().DeepCopyData(SkillConfigItemData.Copy); //修改后的Map
            //引用改为Object 去掉 运行的实例引用
            for (int offest = _map.Count - 1; offest >= 0; offest--)
            {
                var itemData = _map[offest];
                if (itemData._skillRunLine != null)
                {
                    string path = _outPutPath + $"/{itemData._skillRunLine._lineId}.asset";
                    if (File.Exists(path))
                    {
                        var skillRunLine = AssetDatabase.LoadAssetAtPath<SkillRunLine>(path);
                        if (!skillRunLine.Equals(itemData._skillRunLine) && skillRunLine != itemData._skillRunLine)
                        {
                            itemData._skillRunLine = skillRunLine;
                        }
                    }
                }
            }

            HashSet<int> needSave = new HashSet<int>();
            //需要保存的
            foreach (var item in _map)
            {
                needSave.Add(item._id);
            }

            //删除不存在的
            foreach (var item in selfMap)
            {
                if (!needSave.Contains(item._id))
                {
                    string path = _outPutPath + $"/{item._id}.asset";
                    if (File.Exists(path))
                    {
                        AssetDatabase.DeleteAsset(path);
                        AssetDatabase.SaveAssets();
                        AssetDatabase.Refresh();
                    }
                }
            }

            Save();
        }
    }
}